import { _decorator, Component, Node, Prefab, instantiate, Vec2, Vec3, AudioClip, AudioSource, Label, tween, director } from 'cc';
import { GameManager } from './GameManager';
import { TilePrefab } from '../components/TilePrefab';
import { Tile } from '../components/Tile';

const { ccclass, property } = _decorator;

/**
 * 方块类型枚举
 */
export enum TileType {
    NONE = -1,
    RED = 0,
    BLUE = 1,
    GREEN = 2,
    YELLOW = 3,
    PURPLE = 4,
    MAX = 5
}

/**
 * 棋盘管理器
 * 负责管理游戏棋盘和方块逻辑
 */
@ccclass('BoardManager')
export class BoardManager extends Component {
    private static _instance: BoardManager = null;
    
    public static get instance(): BoardManager {
        return this._instance;
    }
    
    @property(Prefab)
    private tilePrefab: Prefab = null;
    
    @property(Node)
    private tilesContainer: Node = null;
    
    @property({type: Number, tooltip: "棋盘行数"})
    private boardRows: number = 8;
    
    @property({type: Number, tooltip: "棋盘列数"})
    private boardCols: number = 8;
    
    @property({type: Number, tooltip: "方块大小"})
    private tileSize: number = 80;
    
    @property({type: Number, tooltip: "方块之间的间距"})
    private tileSpacing: number = 5;
    
    @property({type: Number, min: 3, max: 5, tooltip: "最小匹配数量"})
    private minMatch: number = 3;
    
    @property({type: AudioClip, tooltip: "交换失败音效"})
    private swapFailSound: AudioClip = null;
    
    @property({type: AudioClip, tooltip: "消除音效"})
    private matchSound: AudioClip = null;
    
    @property({type: AudioClip, tooltip: "连击音效"})
    private comboSound: AudioClip = null;
    
    @property(Label)
    private comboLabel: Label = null;
    
    @property(GameManager)
    private gameManager: GameManager = null;
    
    private _tiles: TilePrefab[][] = [];
    private _selectedTile: TilePrefab = null;
    private _isSwapping: boolean = false;
    private _isFilling: boolean = false;
    private _comboCount: number = 0;
    private _comboTimer: number = 0;
    private readonly COMBO_TIMEOUT: number = 2.0; // 连击超时时间（秒）
    
    private _audioSource: AudioSource = null;
    
    // 生命周期函数
    onLoad() {
        // if (BoardManager._instance === null) {
        //     BoardManager._instance = this;
        // } else {
        //     this.node.destroy();
        // }
        
        // 查找GameManager
        this.findGameManager();
        
        // 确保有AudioSource组件
        this._audioSource = this.getComponent(AudioSource);
        if (!this._audioSource) {
            this._audioSource = this.addComponent(AudioSource);
        }
        
        this.initBoard();
    }
    
    /**
     * 查找GameManager实例
     */
    private findGameManager(): void {
        if (!this.gameManager) {
            // 尝试在场景中查找GameManager
            const gameManagerNode = director.getScene().getChildByName('GameManager');
            if (gameManagerNode) {
                this.gameManager = gameManagerNode.getComponent(GameManager);
            }
            
            if (!this.gameManager) {
                console.warn('未找到GameManager引用，某些功能可能无法正常工作');
            }
        }
    }
    
    /**
     * 初始化棋盘
     */
    public initBoard(): void {
        // 清空棋盘
        this.clearBoard();
        
        // 初始化二维数组
        this._tiles = [];
        for (let row = 0; row < this.boardRows; row++) {
            this._tiles[row] = [];
            for (let col = 0; col < this.boardCols; col++) {
                this._tiles[row][col] = null;
            }
        }
        
        // 创建棋盘方块
        this.createTiles();
        
        // 初始检查和消除匹配
        this.checkAndRemoveMatches();
    }
    
    /**
     * 清空棋盘
     */
    private clearBoard(): void {
        // 移除所有方块
        if (this.tilesContainer) {
            this.tilesContainer.removeAllChildren();
        }
        
        // 重置状态
        this._selectedTile = null;
        this._isSwapping = false;
        this._isFilling = false;
    }
    
    /**
     * 创建方块
     */
    private createTiles(): void {
        if (!this.tilePrefab || !this.tilesContainer) return;
        
        for (let row = 0; row < this.boardRows; row++) {
            for (let col = 0; col < this.boardCols; col++) {
                // 创建方块，确保不与上方或左侧的方块形成匹配
                const tileNode = instantiate(this.tilePrefab);
                const tileComponent = tileNode.getComponent(TilePrefab);
                
                if (!tileComponent) {
                    console.error("方块预制体缺少TilePrefab组件");
                    continue;
                }
                
                // 计算方块位置
                const x = col * (this.tileSize + this.tileSpacing);
                const y = row * (this.tileSize + this.tileSpacing);
                tileNode.setPosition(new Vec3(x, y, 0));
                
                // 随机方块类型，但避免形成匹配
                let type = this.getRandomTileTypeWithoutMatch(row, col);
                
                // 初始化方块
                tileComponent.init(type, row, col);
                
                // 添加到容器和数组
                this.tilesContainer.addChild(tileNode);
                this._tiles[row][col] = tileComponent;
                
                // 添加事件监听
                tileNode.on('tileClicked', this.onTileClicked, this);
            }
        }
    }
    
    /**
     * 获取随机方块类型，避免形成匹配
     */
    private getRandomTileTypeWithoutMatch(row: number, col: number): TileType {
        // 可选的方块类型
        const availableTypes = [];
        
        // 检查所有方块类型
        for (let type = TileType.RED; type < TileType.MAX; type++) {
            let willMatch = false;
            
            // 检查是否会与左侧两个方块形成横向匹配
            if (col >= 2) {
                if (this._tiles[row][col-1]?.tileType === type && 
                    this._tiles[row][col-2]?.tileType === type) {
                    willMatch = true;
                }
            }
            
            // 检查是否会与上方两个方块形成纵向匹配
            if (row >= 2) {
                if (this._tiles[row-1][col]?.tileType === type && 
                    this._tiles[row-2][col]?.tileType === type) {
                    willMatch = true;
                }
            }
            
            // 如果不会形成匹配，添加到可选类型
            if (!willMatch) {
                availableTypes.push(type);
            }
        }
        
        // 如果没有合适的类型，返回随机类型
        if (availableTypes.length === 0) {
            return Math.floor(Math.random() * TileType.MAX);
        }
        
        // 返回随机的合适类型
        return availableTypes[Math.floor(Math.random() * availableTypes.length)];
    }
    
    /**
     * 处理Tile组件点击
     * 兼容不同类型的方块组件
     */
    public selectTile(tile: Tile | TilePrefab): void {
        console.log("处理方块选择:", tile);
        
        // 如果正在交换或填充，忽略选择
        if (this._isSwapping || this._isFilling) return;
        
        // 如果没有选中的方块，选中当前方块
        if (!this._selectedTile) {
            this._selectedTile = tile as TilePrefab;
            tile.select();
            return;
        }
        
        // 如果已经选中了当前方块，取消选中
        if (this._selectedTile === tile) {
            this._selectedTile.deselect();
            this._selectedTile = null;
            return;
        }
        
        // 这里应该检查是否相邻，但由于类型不同，暂时简单处理
        const selectedRow = this._selectedTile.row;
        const selectedCol = this._selectedTile.col;
        const tileRow = tile.row;
        const tileCol = tile.col;
        
        const rowDiff = Math.abs(selectedRow - tileRow);
        const colDiff = Math.abs(selectedCol - tileCol);
        
        // 相邻：水平或垂直方向相邻（行或列相差1，另一维度相同）
        const isAdjacent = (rowDiff === 1 && colDiff === 0) || (rowDiff === 0 && colDiff === 1);
        
        if (isAdjacent) {
            // 这里应该交换方块，但由于类型不同，暂时只取消选中
            this._selectedTile.deselect();
            this._selectedTile = null;
            console.log("相邻方块，应该进行交换，但类型不匹配");
        } else {
            // 不相邻，取消选中并选中新方块
            this._selectedTile.deselect();
            this._selectedTile = tile as TilePrefab;
            tile.select();
        }
    }
    
    /**
     * 检查并移除匹配
     */
    private checkAndRemoveMatches(): boolean {
        const matches = this.findAllMatches();
        
        if (matches.length > 0) {
            this.removeMatches(matches);
            return true;
        }
        
        return false;
    }
    
    /**
     * 查找所有匹配
     */
    private findAllMatches(): TilePrefab[][] {
        const allMatches: TilePrefab[][] = [];
        
        // 检查水平匹配
        for (let row = 0; row < this.boardRows; row++) {
            for (let col = 0; col < this.boardCols - 2; col++) {
                const match = this.checkMatch(row, col, 0, 1);
                if (match.length >= this.minMatch) {
                    allMatches.push(match);
                }
            }
        }
        
        // 检查垂直匹配
        for (let row = 0; row < this.boardRows - 2; row++) {
            for (let col = 0; col < this.boardCols; col++) {
                const match = this.checkMatch(row, col, 1, 0);
                if (match.length >= this.minMatch) {
                    allMatches.push(match);
                }
            }
        }
        
        return allMatches;
    }
    
    /**
     * 检查从指定位置开始的匹配
     */
    private checkMatch(row: number, col: number, rowDir: number, colDir: number): TilePrefab[] {
        const matches: TilePrefab[] = [];
        const startTile = this._tiles[row][col];
        
        if (!startTile || startTile.tileType === TileType.NONE) {
            return matches;
        }
        
        matches.push(startTile);
        
        // 检查相邻方块
        for (let i = 1; i < Math.max(this.boardRows, this.boardCols); i++) {
            const newRow = row + i * rowDir;
            const newCol = col + i * colDir;
            
            // 检查边界
            if (newRow >= this.boardRows || newCol >= this.boardCols) {
                break;
            }
            
            const nextTile = this._tiles[newRow][newCol];
            
            // 检查类型匹配
            if (nextTile && nextTile.tileType === startTile.tileType) {
                matches.push(nextTile);
            } else {
                break;
            }
        }
        
        return matches;
    }
    
    /**
     * 移除匹配的方块
     */
    private removeMatches(matches: TilePrefab[][]): void {
        this._isFilling = true;
        
        // 标记所有匹配的方块
        let totalMatched = 0;
        matches.forEach(match => {
            match.forEach(tile => {
                if (!tile.isMatched()) {
                    tile.markAsMatched();
                    totalMatched++;
                }
            });
        });
        
        // 计算得分和连击
        if (totalMatched > 0 && this.gameManager) {
            const points = totalMatched * 10;
            this._comboCount++;  // 增加连击数
            
            // 播放消除音效
            if (this._audioSource && this.matchSound) {
                this._audioSource.playOneShot(this.matchSound);
            }
            
            // 播放连击音效（当连击数大于1时）
            if (this._comboCount > 1 && this._audioSource && this.comboSound) {
                this._audioSource.playOneShot(this.comboSound);
            }
            
            // 更新连击显示
            this.updateComboDisplay();
            
            // 计算连击加成
            const comboMultiplier = this._comboCount > 1 ? this._comboCount : 1;
            this.gameManager.addScore(points * comboMultiplier);
            
            // 重置连击计时器
            this._comboTimer = 0;
        }
        
        // 播放消除动画
        let pendingAnimations = 0;
        matches.forEach(match => {
            match.forEach(tile => {
                pendingAnimations++;
                tile.playMatchAnimation(() => {
                    pendingAnimations--;
                    if (pendingAnimations === 0) {
                        // 所有动画完成，填充空位
                        this.fillEmptySpaces();
                    }
                });
            });
        });
    }
    
    /**
     * 更新连击显示
     */
    private updateComboDisplay(): void {
        if (!this.comboLabel) return;
        
        if (this._comboCount > 1) {
            // 显示连击文本
            this.comboLabel.string = `${this._comboCount}连击！`;
            this.comboLabel.node.active = true;
            
            // 播放连击动画
            this.comboLabel.node.scale = new Vec3(1.5, 1.5, 1);
            tween(this.comboLabel.node)
                .to(0.2, { scale: new Vec3(1, 1, 1) })
                .start();
        } else {
            this.comboLabel.node.active = false;
        }
    }
    
    /**
     * 填充空位
     */
    private fillEmptySpaces(): void {
        // 从下往上遍历棋盘
        for (let col = 0; col < this.boardCols; col++) {
            // 将已匹配的方块标记为空
            for (let row = 0; row < this.boardRows; row++) {
                const tile = this._tiles[row][col];
                if (tile && tile.isMatched()) {
                    // 移除节点
                    tile.node.removeFromParent();
                    this._tiles[row][col] = null;
                }
            }
            
            // 将上方的方块下落填充空位
            let emptyRow = -1;
            for (let row = 0; row < this.boardRows; row++) {
                if (!this._tiles[row][col]) {
                    // 找到一个空位
                    if (emptyRow === -1) {
                        emptyRow = row;
                    }
                } else if (emptyRow !== -1) {
                    // 找到一个方块，可以下落
                    const tile = this._tiles[row][col];
                    
                    // 更新数组
                    this._tiles[emptyRow][col] = tile;
                    this._tiles[row][col] = null;
                    
                    // 更新方块属性
                    tile.row = emptyRow;
                    
                    // 计算新位置
                    const newY = emptyRow * (this.tileSize + this.tileSpacing);
                    const newPos = new Vec3(tile.node.position.x, newY, 0);
                    
                    // 播放下落动画
                    tile.playMoveAnimation(newPos);
                    
                    // 移动空位指针
                    emptyRow++;
                }
            }
            
            // 在顶部创建新方块
            for (let row = 0; row < this.boardRows; row++) {
                if (!this._tiles[row][col]) {
                    this.createNewTile(row, col);
                }
            }
        }
        
        // 延迟检查新的匹配
        this.scheduleOnce(() => {
            const hasMatches = this.checkAndRemoveMatches();
            if (!hasMatches) {
                this._isFilling = false;
                this._comboCount = 0;  // 重置连击数
                if (this.comboLabel) {
                    this.comboLabel.node.active = false;
                }
            }
        }, 0.5);
    }
    
    /**
     * 创建新方块
     */
    private createNewTile(row: number, col: number): void {
        if (!this.tilePrefab || !this.tilesContainer) return;
        
        // 创建方块
        const tileNode = instantiate(this.tilePrefab);
        const tileComponent = tileNode.getComponent(TilePrefab);
        
        if (!tileComponent) {
            console.error("方块预制体缺少TilePrefab组件");
            return;
        }
        
        // 计算方块位置（初始位置在顶部之外）
        const x = col * (this.tileSize + this.tileSpacing);
        const y = (this.boardRows + 1) * (this.tileSize + this.tileSpacing); // 在棋盘顶部之外
        tileNode.setPosition(new Vec3(x, y, 0));
        
        // 随机方块类型
        const type = Math.floor(Math.random() * TileType.MAX);
        
        // 初始化方块
        tileComponent.init(type, row, col);
        
        // 添加到容器和数组
        this.tilesContainer.addChild(tileNode);
        this._tiles[row][col] = tileComponent;
        
        // 确保绑定事件监听器
        tileNode.on('tileClicked', this.onTileClicked, this);
        console.log(`新方块添加事件监听: row=${row}, col=${col}`);
        
        // 计算最终位置
        const finalY = row * (this.tileSize + this.tileSpacing);
        const finalPos = new Vec3(x, finalY, 0);
        
        // 播放动画
        tileComponent.playMoveAnimation(finalPos);
    }
    
    /**
     * 方块点击事件处理
     */
    public onTileClicked(event: any) {
        console.log("收到方块点击事件:", event);
        
        // 如果正在交换或填充，忽略点击
        if (this._isSwapping || this._isFilling) {
            console.log("正在执行动画，忽略点击");
            return;
        }
        
        const { row, col } = event.detail;
        console.log(`处理方块点击: row=${row}, col=${col}`);
        
        const clickedTile = this._tiles[row][col];
        
        if (!clickedTile) {
            console.error(`点击了无效的方块位置: row=${row}, col=${col}, 方块不存在`);
            return;
        }
        
        console.log(`BoardManager received click: row=${row}, col=${col}, 方块类型: ${clickedTile.tileType}`);

        if (!this._selectedTile) {
            // 第一次选择
            this._selectedTile = clickedTile;
            clickedTile.select();
            console.log("选中第一个方块");
        } else if (this._selectedTile === clickedTile) {
            // 再次点击同一个方块，取消选择
            this._selectedTile.deselect();
            this._selectedTile = null;
            console.log("取消选择方块");
        } else {
            // 尝试交换方块
            if (this.areAdjacent(this._selectedTile, clickedTile)) {
                console.log("尝试交换相邻方块");
                // 直接交换方块，swapTiles内部会处理deselect和设置_selectedTile = null
                this.swapTiles(this._selectedTile, clickedTile);
                // 不需要再次调用deselect，因为swapTiles已经处理了
            } else {
                console.log("选择的方块不相邻，切换选择");
                // 不相邻，选择新方块
                this._selectedTile.deselect();
                this._selectedTile = clickedTile;
                clickedTile.select();
            }
        }
    }
    
    update(dt: number) {
        // 更新连击计时器
        if (this._comboCount > 0) {
            this._comboTimer += dt;
            if (this._comboTimer >= this.COMBO_TIMEOUT) {
                // 连击超时，重置连击
                this._comboCount = 0;
                this._comboTimer = 0;
                if (this.comboLabel) {
                    this.comboLabel.node.active = false;
                }
            }
        }
    }
    
    /**
     * 获取方块大小
     */
    public getTileSize(): number {
        return this.tileSize;
    }
    
    /**
     * 获取方块间距
     */
    public getTileGap(): number {
        return this.tileSpacing;
    }
    
    /**
     * 设置方块容器
     */
    public setTilesContainer(container: Node): void {
        if (container) {
            this.tilesContainer = container;
        }
    }
    
    /**
     * 检查两个方块是否相邻
     */
    private areAdjacent(tile1: TilePrefab, tile2: TilePrefab): boolean {
        const rowDiff = Math.abs(tile1.row - tile2.row);
        const colDiff = Math.abs(tile1.col - tile2.col);
        
        // 相邻：水平或垂直方向相邻（行或列相差1，另一维度相同）
        return (rowDiff === 1 && colDiff === 0) || (rowDiff === 0 && colDiff === 1);
    }
    
    /**
     * 交换两个方块
     */
    private swapTiles(tile1: TilePrefab, tile2: TilePrefab): void {
        this._isSwapping = true;
        
        // 取消选中状态
        tile1.deselect();
        this._selectedTile = null;
        
        // 保存原始位置
        const pos1 = tile1.node.position.clone();
        const pos2 = tile2.node.position.clone();
        
        // 交换数组中的引用
        this._tiles[tile1.row][tile1.col] = tile2;
        this._tiles[tile2.row][tile2.col] = tile1;
        
        // 交换行列值
        const tempRow = tile1.row;
        const tempCol = tile1.col;
        tile1.row = tile2.row;
        tile1.col = tile2.col;
        tile2.row = tempRow;
        tile2.col = tempCol;
        
        // 播放移动动画
        tile1.playMoveAnimation(pos2, () => {
            // 检查是否有匹配
            const hasMatches = this.checkAndRemoveMatches();
            
            if (!hasMatches) {
                // 没有匹配，交换回来
                this.swapTilesBack(tile1, tile2, pos1, pos2);
            } else {
                this._isSwapping = false;
            }
        });
        
        tile2.playMoveAnimation(pos1);
    }
    
    /**
     * 交换回方块（无效移动）
     */
    private swapTilesBack(tile1: TilePrefab, tile2: TilePrefab, pos1: Vec3, pos2: Vec3): void {
        // 播放交换失败音效
        if (this._audioSource && this.swapFailSound) {
            this._audioSource.playOneShot(this.swapFailSound);
        }
        
        // 交换数组中的引用
        this._tiles[tile1.row][tile1.col] = tile2;
        this._tiles[tile2.row][tile2.col] = tile1;
        
        // 交换行列值
        const tempRow = tile1.row;
        const tempCol = tile1.col;
        tile1.row = tile2.row;
        tile1.col = tile2.col;
        tile2.row = tempRow;
        tile2.col = tempCol;
        
        // 播放移动动画
        tile1.playMoveAnimation(pos1, () => {
            this._isSwapping = false;
        });
        
        tile2.playMoveAnimation(pos2);
    }

    /**
     * 处理匹配，移除匹配的方块，并添加分数
     */
    private handleMatches(matches: TilePrefab[]): void {
        const totalMatched = matches.length;
        
        // 播放消除音效
        if (this._audioSource && this.matchSound) {
            this._audioSource.playOneShot(this.matchSound);
        }
        
        // 计算得分和连击
        if (totalMatched > 0) {
            const points = totalMatched * 10;
            this._comboCount++;  // 增加连击数
            
            // 显示连击文本
            if (this._comboCount > 1 && this.comboLabel) {
                this.comboLabel.string = `${this._comboCount}连击!`;
                this.comboLabel.node.active = true;
                
                // 播放连击音效
                if (this._audioSource && this.comboSound) {
                    this._audioSource.playOneShot(this.comboSound);
                }
                
                // 隐藏连击文本
                this.scheduleOnce(() => {
                    if (this.comboLabel) {
                        this.comboLabel.node.active = false;
                    }
                }, 1.5);
            }
            
            // 计算连击加成
            const comboMultiplier = this._comboCount > 1 ? this._comboCount : 1;
            const totalPoints = points * comboMultiplier;
            
            // 添加分数到GameManager
            const gameManagerNode = director.getScene().getChildByName('GameManager');
            if (gameManagerNode) {
                const gameManager = gameManagerNode.getComponent(GameManager);
                if (gameManager) {
                    console.log(`添加分数: ${totalPoints}分 (${points}基础分 x ${comboMultiplier}连击加成)`);
                    gameManager.addScore(totalPoints);
                } else {
                    console.warn("未找到GameManager组件，无法添加分数");
                }
            } else {
                console.warn("未找到GameManager节点，无法添加分数");
            }
            
            // 重置连击计时器
            this.unschedule(this.resetCombo);
            this.scheduleOnce(this.resetCombo, this.COMBO_TIMEOUT);
        }
        
        // 为每个匹配的方块播放消除动画
        for (const tile of matches) {
            // 检查方块是否有特效方法
            if (typeof tile.playEliminateEffect === 'function') {
                tile.playEliminateEffect();
            } else {
                // 如果没有特效方法，直接移除
                tile.node.removeFromParent();
                console.warn("方块缺少playEliminateEffect方法，直接移除");
            }
        }
    }

    /**
     * 重置连击计数
     */
    private resetCombo = (): void => {
        console.log("重置连击计数");
        this._comboCount = 0;
        this._comboTimer = 0;
        if (this.comboLabel) {
            this.comboLabel.node.active = false;
        }
    }
} 